

using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Magic.Core.Entity;
using Mapster;
using Microsoft.AspNetCore.Mvc;

using SqlSugar;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Magic.Core.Service;

/// <summary>
/// 系统应用服务
/// </summary>
public class SysAppService : ISysAppService
{
    private readonly SqlSugarRepository<SysApp> _sysAppRep;    // 应用表仓储
    private readonly ISysMenuService _sysMenuService;

    public SysAppService(SqlSugarRepository<SysApp> sysAppRep,
                         ISysMenuService sysMenuService)
    {
        _sysAppRep = sysAppRep;
        _sysMenuService = sysMenuService;
    }


    public async Task<List<SysApp>> GetLoginApps(long userId)
    {
        var apps = _sysAppRep.Where(u => u.Status == (int)CommonStatus.ENABLE);
        if (!UserManager.IsSuperAdmin)
        {
            var appCodeList = await _sysMenuService.GetUserMenuAppCodeList(userId);
            apps = apps.Where(u => appCodeList.Contains(u.Code));
        }
        var appList = await apps.OrderBy(u => u.Active, OrderByType.Desc).OrderBy(u => u.Sort).ToListAsync();

        return appList;
    }

    public async Task<PageList<SysApp>> PageList(QuerySysAppPageInput input)
    {
        var apps = await _sysAppRep.AsQueryable()
             .WhereIF(!string.IsNullOrWhiteSpace(input.Name), m => m.Name.Contains(input.Name.Trim()))
              .WhereIF(!string.IsNullOrWhiteSpace(input.Code), m => m.Code.Contains(input.Code))
              .ToPagedListAsync(input.PageNo, input.PageSize);
        return apps.McPagedResult();
    }

    public async Task<SysApp> Get(Core.PrimaryKeyParam input)
    {
        return await _sysAppRep.SingleAsync(input.Id);
    }

    public async Task<List<SysApp>> List()
    {
        return await _sysAppRep.Where(u => u.Status == (int)CommonStatus.ENABLE).ToListAsync();
    }


    public async Task Add(AddSysAppParam input)
    {
        var isExist = await _sysAppRep.AnyAsync(u => u.Name == input.Name || u.Code == input.Code);
        if (isExist)
            throw Oops.Bah(ErrorCode.D5000);

        if (input.Active == YesOrNot.Y.ToString())
        {
            isExist = await _sysAppRep.AnyAsync(u => u.Active == input.Active);
            if (isExist)
                throw Oops.Bah(ErrorCode.D5001);
        }

        var app = input.Adapt<SysApp>();
        await _sysAppRep.InsertAsync(app);
    }

    public async Task Delete(PrimaryKeyParam input)
    {
        var app = await _sysAppRep.FirstOrDefaultAsync(u => u.Id == input.Id);
        // 该应用下是否有状态为正常的菜单
        var hasMenu = await _sysMenuService.HasMenu(app.Code);
        if (hasMenu)
            throw Oops.Oh(ErrorCode.D5002);

        await _sysAppRep.DeleteAsync(app);
    }

    public async Task Update(EditSysAppParam input)
    {
        var isExist = await _sysAppRep.AnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id);
        if (isExist)
            throw Oops.Oh(ErrorCode.D5000);

        if (input.Active == YesOrNot.Y.ToString())
        {
            isExist = await _sysAppRep.AnyAsync(u => u.Active == input.Active && u.Id != input.Id);
            if (isExist)
                throw Oops.Oh(ErrorCode.D5001);
        }

        var app = input.Adapt<SysApp>();
        await _sysAppRep.AsUpdateable(app).IgnoreColumns(it => new { it.Status }).ExecuteCommandAsync();
    }

    public async Task SetAsDefault(PrimaryKeyParam input)
    {
        var apps = await _sysAppRep.Where(u => u.Status == (int)CommonStatus.ENABLE).ToListAsync();
        apps.ForEach(u =>
        {
            if (u.Id == input.Id)
            {
                u.Active = YesOrNot.Y.ToString();
            }
            else
            {
                u.Active = YesOrNot.N.ToString();
            }
        });
        await _sysAppRep.UpdateAsync(apps);
    }

    public async Task ChangeStatus(ChangeSysAppStatusParam input)
    {
        if (!Enum.IsDefined(typeof(CommonStatus), input.Status))
            throw Oops.Oh(ErrorCode.D3005);

        var app = await _sysAppRep.FirstOrDefaultAsync(u => u.Id == input.Id);
        app.Status = input.Status;
        await _sysAppRep.UpdateAsync(app);
    }
}
